﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using GrayParrot.Communications.Core;
using GrayParrot.Communications.Notifications;
using System.Configuration;
using GrayParrot.ServiceBus;
using GrayParrot.Configuration;
using GrayParrot.ServiceBus.Configuration;
using GrayParrot.Communications.Configuration;

namespace GrayParrot.Communications.Notifications
{
    public interface Empty : Operations { }

    public interface Operations { CommunicationBag Create(string body); bool Send(string body); }

    public interface AsEmail<TRemainder> : Operations { TRemainder AsEmail(); TRemainder AsEmail(EmailSettingsOvveride emailSettings); }
    public interface AsMessage<TRemainder> : Operations { TRemainder AsMessage(); }
    public interface AsNotification<TRemainder> : Operations { TRemainder AsNotification(); }

    public interface Not_AsEmail : Operations, AsMessage<Not_AsEmailAsMessage>, AsNotification<Not_AsEmailAsNotification> { }
    public interface Not_AsMessage : Operations, AsEmail<Not_AsEmailAsMessage>, AsNotification<Not_AsMessageAsNotification> { }
    public interface Not_AsNotification : Operations, AsEmail<Not_AsEmailAsNotification>, AsMessage<Not_AsMessageAsNotification> { }

    public interface Not_AsEmailAsMessage : Operations, AsNotification<Empty> { }
    public interface Not_AsMessageAsNotification : Operations, AsEmail<Empty> { }
    public interface Not_AsEmailAsNotification : Operations, AsMessage<Empty> { }

    public class EmailSettingsOvveride
    {
        public string From { get; set; }

        public string[] To { get; set; }

        public string[] Cc { get; set; }
    }

    [EditorBrowsable(EditorBrowsableState.Never)]
    public class AbstractNotific
    {
        [EditorBrowsable(EditorBrowsableState.Never)]
        public virtual CommunicationBag Create(string body) { return null; }

        [EditorBrowsable(EditorBrowsableState.Never)]
        public virtual bool Send(string body) { return false; }
    }

    [EditorBrowsable(EditorBrowsableState.Never)]
    public class NotificationInternal : AbstractNotific, Operations, AsEmail<Not_AsEmail>, AsMessage<Not_AsMessage>, AsNotification<Not_AsNotification>,
                                Not_AsEmail, Not_AsMessage, Not_AsNotification,
                                Not_AsEmailAsMessage, Not_AsMessageAsNotification, Not_AsEmailAsNotification, Empty
    {
        private string m_type = string.Empty;
        private MessageSeverity m_severity = MessageSeverity.Info;
        private CommunicationMedia m_communicationType = CommunicationMedia.Null;
        private string m_body = string.Empty;
        private EmailSettingsOvveride emailSettings = null;

        public EmailSettingsOvveride EmailSettings
        {
            get { return emailSettings; }
            internal set { emailSettings = value; }
        }

        public string Body
        {
            get { return m_body; }
            protected internal set { m_body = value; }
        }

        public CommunicationMedia CommunicationType
        {
            get { return m_communicationType; }
            protected internal set { m_communicationType = value; }
        }

        public string Type
        {
            get { return m_type; }
            set { m_type = value; }
        }

        public MessageSeverity Severity
        {
            get { return m_severity; }
            internal set { m_severity = value; }
        }

        private void SetAsEmail()
        {
            if (!m_communicationType.HasFlag(CommunicationMedia.Email))
            {
                m_communicationType |= CommunicationMedia.Email;
            }
        }
        private void SetAsEmail(EmailSettingsOvveride emailSettings)
        {
            this.emailSettings = emailSettings;

            if (!m_communicationType.HasFlag(CommunicationMedia.Email))
            {
                m_communicationType |= CommunicationMedia.Email;
            }
        }
        private void SetAsMessage()
        {
            if (!m_communicationType.HasFlag(CommunicationMedia.Message))
            {
                m_communicationType |= CommunicationMedia.Message;
            }
        }
        private void SetAsNotification()
        {
            if (!m_communicationType.HasFlag(CommunicationMedia.Notification))
            {
                m_communicationType |= CommunicationMedia.Notification;
            }
        }

        Not_AsEmailAsMessage AsEmail<Not_AsEmailAsMessage>.AsEmail() { SetAsEmail(); return (Not_AsEmailAsMessage)AsEmail(); }
        Not_AsEmailAsNotification AsEmail<Not_AsEmailAsNotification>.AsEmail() { SetAsEmail(); return (Not_AsEmailAsNotification)AsEmail(); }
        Empty AsEmail<Empty>.AsEmail() { SetAsEmail(); return (Empty)AsEmail(); }
        public Not_AsEmail AsEmail()
        {
            SetAsEmail();
            return (Not_AsEmail)this;
        }

        Not_AsEmailAsMessage AsEmail<Not_AsEmailAsMessage>.AsEmail(EmailSettingsOvveride emailSettings) { SetAsEmail(emailSettings); return (Not_AsEmailAsMessage)AsEmail(emailSettings); }
        Not_AsEmailAsNotification AsEmail<Not_AsEmailAsNotification>.AsEmail(EmailSettingsOvveride emailSettings) { SetAsEmail(emailSettings); return (Not_AsEmailAsNotification)AsEmail(emailSettings); }
        Empty AsEmail<Empty>.AsEmail(EmailSettingsOvveride emailSettings) { SetAsEmail(emailSettings); return (Empty)AsEmail(emailSettings); }
        public Not_AsEmail AsEmail(EmailSettingsOvveride emailSettings)
        {
            SetAsEmail(emailSettings);
            return (Not_AsEmail)this;
        }

        Not_AsEmailAsMessage AsMessage<Not_AsEmailAsMessage>.AsMessage() { SetAsMessage(); return (Not_AsEmailAsMessage)AsMessage(); }
        Not_AsMessageAsNotification AsMessage<Not_AsMessageAsNotification>.AsMessage() { SetAsMessage(); return (Not_AsMessageAsNotification)AsMessage(); }
        Empty AsMessage<Empty>.AsMessage() { SetAsMessage(); return (Empty)AsMessage(); }
        public Not_AsMessage AsMessage()
        {
            SetAsMessage();
            return (Not_AsMessage)this;
        }

        Not_AsEmailAsNotification AsNotification<Not_AsEmailAsNotification>.AsNotification() { SetAsNotification(); return (Not_AsEmailAsNotification)AsNotification(); }
        Not_AsMessageAsNotification AsNotification<Not_AsMessageAsNotification>.AsNotification() { SetAsNotification(); return (Not_AsMessageAsNotification)AsNotification(); }
        Empty AsNotification<Empty>.AsNotification() { SetAsNotification(); return (Empty)AsNotification(); }
        public Not_AsNotification AsNotification()
        {
            SetAsNotification();
            return (Not_AsNotification)this;
        }

        public NotificationInternal()
        {

        }

        [EditorBrowsable(EditorBrowsableState.Never)]
        public NotificationInternal(string type)
        {
            m_type = type;
        }

        [EditorBrowsable(EditorBrowsableState.Never)]
        public NotificationInternal(MessageSeverity severity)
        {
            m_severity = severity;
        }

        [EditorBrowsable(EditorBrowsableState.Never)]
        public NotificationInternal(MessageSeverity severity, string type)
        {
            m_severity = severity;
            m_type = type;
        }

        public override CommunicationBag Create(string body)
        {
            CommunicationBag retValue = new CommunicationBag();
            retValue.Body = "";
            retValue.CreationDate = DateTime.Now;
            retValue.Severity = m_severity;
            retValue.Type = m_type;
            retValue.CommunicationType = m_communicationType;
            retValue.Body = body;
            
            return retValue;
        }

        public override bool Send(string body)
        {
            bool retValue = false;

            NotificationMessage m_msg = new NotificationMessage();
            m_msg.MessageBody = body;
            m_msg.ExtendToGui = m_communicationType.HasFlag(CommunicationMedia.Notification);
            m_msg.UseEmail = m_communicationType.HasFlag(CommunicationMedia.Email);
            m_msg.PeristentMessage = m_communicationType.HasFlag(CommunicationMedia.Message);
            m_msg.Severity = this.Severity;
            m_msg.Type = (string.IsNullOrWhiteSpace(this.Type) ? "INFO" : this.Type);

            if (this.emailSettings != null)
            {
                m_msg.EmailSettings = this.emailSettings;
            }

            ConfigurationManagerHelper pp = new ConfigurationManagerHelper();
            CommunicationsSettings m_commCfg = pp.GetCommunicationsSettings();

            Subscription m_subCfg = pp.GetSubscription(m_commCfg.Endpoint, m_commCfg.Subscription);
            string m_messageName = m_subCfg.MessageName;

            ServiceBusMessageBag<NotificationMessage> m_sbMsg = new ServiceBusMessageBag<NotificationMessage>(m_messageName);
            m_sbMsg.Body = m_msg;

            //using (Publisher p = new Publisher(m_subCfg))
            //{
            //    switch (m_subCfg.FormatType)
            //    {
            //        case FormatTypes.Binary:
            //            retValue = p.Send(m_sbMsg.ToBrokeredMessage());
            //            break;
            //        case FormatTypes.Xml:
            //            retValue = p.Send(m_sbMsg.ToXMLBrokeredMessage());
            //            break;
            //        default:
            //            break;
            //    }
            //}

            return retValue;
        }
    }

    public interface IWithBody
    {
        NotF3 WithBody(string body);
    }

    public interface IWithSeverity
    {
        NotF2 OfType(string type);
    }

    public interface IOfType
    {
        NotF1 WithSeverity(MessageSeverity severity);
    }

    [EditorBrowsable(EditorBrowsableState.Never)]
    public class NotF3
    {
        public NotificationInternal WithBody(string body)
        {
            return new NotificationInternal() { Body = body };
        }

        public NotF3(string body)
        {

        }
    }

    [EditorBrowsable(EditorBrowsableState.Never)]
    public class NotF2
    {
        private string m_type = string.Empty;

        public NotF2(string type)
        {
            m_type = type;
        }

        public NotificationInternal WithSeverity(MessageSeverity severity)
        {
            return new NotificationInternal(severity, m_type);
        }
    }

    [EditorBrowsable(EditorBrowsableState.Never)]
    public class NotF1
    {
        MessageSeverity m_severity = MessageSeverity.Info;

        public NotF1(MessageSeverity severity)
        {
            m_severity = severity;
        }

        public NotificationInternal OfType(string type)
        {
            return new NotificationInternal(m_severity, type);
        }
    }

    public class Notification : IWithSeverity, IOfType, INotification
    {
        public NotF2 OfType(string type)
        {
            return new NotF2(type);
        }

        public NotF1 WithSeverity(MessageSeverity severity)
        {
            return new NotF1(severity);
        }
    }

    [EditorBrowsable(EditorBrowsableState.Never)]
    public class test
    {
        public test()
        {
            //EmailSettings m_es = new EmailSettings();
            //m_es.From = "cc@pp.it";
            //m_es.To = new EmailsCollection();
            //m_es.To.Add(new EmailItem() { Email = "" });
            //m_es.To.Add(new EmailItem() { Email = "" });
            //m_es.To.Add(new EmailItem() { Email = "" });

            //Notification pp = new Notification();
            ////pp.WithSeverity(MessageSeverity.Info).OfType("ANNULLO").AsEmail().AsMessage().AsNotification().Send("esempio di comunicazione");
            //pp.WithSeverity(MessageSeverity.Info).OfType("ANNULLO").AsEmail(m_es).AsMessage().AsNotification().Send("esempio di comunicazione");


        }
    }

}
